import {
  Children,
  cloneElement,
  createElement,
  CSSProperties,
  HTMLAttributes,
  isValidElement,
  useEffect,
  useState,
  type FC,
} from 'react';
import classNames from 'classnames';
import { progressDefaultProps } from './defaultProps';
import type { ProgressOptions } from './type';
import ProgressBar from './ProgressBar';
import ProgressLabel from './ProgressLabel';
import { ProgressContextProvider, useProgressContext } from './ProgressContext';
import { trimEnd, trimStart } from '../_util/trim';

export interface ProgressProps extends ProgressOptions, Omit<HTMLAttributes<HTMLDivElement>, 'color'> {}

interface ProgressInterface extends FC<ProgressProps> {
  Bar: typeof ProgressBar;
  Label: typeof ProgressLabel;
}

const Child: FC<ProgressProps> = (props) => {
  const {
    className,
    ui,
    percentage,
    indicating,
    size,
    color,
    multiple,
    active,
    success,
    warning,
    error,
    disabled,
    indeterminate,
    right,
    inverted,
    attached,
    children,
    forwardedRef,
    ...progressProps
  } = props;
  const [state, setState] = useState<string>();
  const [percentStart, setPercentStart] = useState<Array<number>>([]);
  const [percentEnd, setPercentEnd] = useState<Array<number>>([]);
  const [percent, setPercent] = useState<number | string | Array<number | string> | undefined>(percentage);
  const [states, setStates] = useProgressContext();

  useEffect(() => {
    if (multiple) {
      const percents = percentage!
        .toString()
        .split(',')
        .map((item) => Number(item.trim()));
      const total = percents.reduce((a, b) => a + b);
      if (total > 100) {
        console.error('Progress: Value specified is above 100%', total);
        setPercent(undefined);
      } else {
        setPercent(percents);
      }
    } else {
      if (percentage! < 0) {
        setPercent(0);
      } else if (percentage! > 100) {
        setPercent(100);
      } else {
        setPercent(percentage);
      }

      if (percentage === 100 || percentage! > 100) {
        if (warning) {
          setState('warning');
        } else if (error) {
          setState('error');
        } else if (success) {
          setState('success');
        } else {
          setState(undefined);
        }
      } else {
        setState(undefined);
      }
    }
  }, [percentage]);

  useEffect(() => {
    setStates({ ...states, percent });
    if (typeof percent === 'object') {
      const aa = percent.join(',');
      setPercentStart(aa.split(',').map((item) => Number(item.trim())) as Array<number>);
      setPercentEnd(aa.split(',').map((item) => Number(item.trim())) as Array<number>);
    }
  }, [percent]);

  let i = 0;

  const content = Children.map(children, (item) => {
    if (isValidElement(item) && item.type === ProgressBar) {
      let style: CSSProperties = {};
      let progress;

      if (multiple) {
        if (typeof percent === 'object') {
          if (percent[i] === 0) {
            style = { display: 'none' };
          } else {
            style = { width: `${percent[i]}%` };
          }
          if (i === percent.length - trimStart(percentStart, 0).length) {
            style = { ...style, borderTopRightRadius: 0, borderBottomRightRadius: 0 };
          } else if (i === trimEnd(percentEnd, 0).length - 1) {
            style = { ...style, borderTopLeftRadius: 0, borderBottomLeftRadius: 0 };
          } else {
            style = { ...style, borderRadius: 0 };
          }
          progress = item.props.progress && (item.props.progress as string).replace('{percent}', percent[i].toString());
        }
      } else if (percent) {
        style = { width: `${percent}%` };
        progress = item.props.progress && (item.props.progress as string).replace('{percent}', percent.toString());
      }

      i++;

      return cloneElement(item, {
        ...item.props,
        style: { transitionDuration: '300ms', ...style, ...item.props.style },
        progress,
      });
    } else {
      return item;
    }
  });

  return createElement(
    'div',
    {
      ref: forwardedRef,
      className: classNames(
        { ui, active, indicating, multiple, disabled, inverted },
        indeterminate,
        { indeterminate },
        size,
        color,
        { right, aligned: right },
        attached,
        { attached },
        'progress',
        state,
        className,
      ),
      'data-percent': multiple ? (typeof percent === 'object' ? percent.join(',') : percent ?? percentage) : percent,
      ...progressProps,
    },
    content,
  );
};

const Progress: ProgressInterface = (props) => {
  const { percentage } = props;

  return createElement(ProgressContextProvider, { initialValue: { percent: percentage } }, <Child {...props} />);
};

Progress.displayName = 'Progress';
Progress.defaultProps = progressDefaultProps;

Progress.Bar = ProgressBar;
Progress.Label = ProgressLabel;

export default Progress;
